package com.web.itemService.Controller;

import cn.hutool.core.lang.UUID;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.web.itemService.properties.CpolarHttpProperty;
import com.web.itemService.service.userService;
import com.web.itemService.utils.changeCodeUtils;
import entity.Result;
import entity.User;
import entity.WeChatUser;
import entity.redisToSaveCodeInformation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.web.itemService.utils.jwtUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/wcCheck")
public class WeChatController {
    @Autowired
    jwtUtils jwtUtils;
    @Autowired
    changeCodeUtils changeCodeUtils;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    userService  userService;
    @Autowired
    CpolarHttpProperty httpProperty;

    @GetMapping("/get")
    public String get(@RequestParam(value = "signature") String signature, @RequestParam(value = "timestamp") String timestamp, @RequestParam(value = "nonce") String nonce, @RequestParam(value = "echostr") String echostr) {
        log.info("收到微信请求 : echos tr :{}", echostr);
        //TODO 校验请求
        return echostr;
    }

    @GetMapping("/wxLogin")
    public void wxLogin(HttpServletResponse response, HttpServletRequest request) throws IOException {
        String token = request.getHeader("token");
        redisToSaveCodeInformation redisToSaveCodeInformation = new redisToSaveCodeInformation();
        redisToSaveCodeInformation.setState(0);
        redisToSaveCodeInformation.setInformation(null);
        redisTemplate.opsForValue().set(token, redisToSaveCodeInformation,360, TimeUnit.SECONDS);
        log.info("这是前端返回的token:{}", token);
        String redirect_Url = URLEncoder.encode( httpProperty.getUrl()+"/wcCheck/wxCallback", StandardCharsets.UTF_8);
        log.info("redirect_Url:{}", redirect_Url);
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxdf1c519996b434cb&redirect_uri=" + redirect_Url + "&response_type=code&scope=snsapi_userinfo&state=" + token + "#wechat_redirect";
        QrConfig config = new QrConfig(1000, 1000);
        config.setErrorCorrection(ErrorCorrectionLevel.H);
        //TODO 这里给前端返回用户唯一ID的二维码
        response.setContentType("image/png");
        log.info("生成了图片");
        QrCodeUtil.generate(url, 300, 300, "jpg", response.getOutputStream());
    }


    @GetMapping("/wxCallback")
    public String wcCallback(@RequestParam(value = "code") String code, @RequestParam(value = "state") String state) throws JsonProcessingException {
        log.info("回调获取的 code:{} , state： {}", code, state);
        //TODO 这里获取用户唯一ID对应的State
        ObjectMapper objectMapper = new ObjectMapper();

        //TODO 查找是否用户已经绑定了微信openID &&  将redisToSaveCodeInformation 中的information 携带wecChatUser
        //TODO 这里用code获取access_token
        WeChatUser weChatUser = changeCodeUtils.togetAccess_token(code);
        //TODO 这里将扫码时的未设置的 information 设置信息
        redisToSaveCodeInformation redisToSaveCodeInformation = new redisToSaveCodeInformation();
        redisToSaveCodeInformation.setInformation(weChatUser);
        redisToSaveCodeInformation.setState(1);
        //TODO 这里检查登录是否有效并将redisToSaveCodeInformation的生命周期重置
        entity.redisToSaveCodeInformation redisToSaveCodeInformationToCheckExist = (redisToSaveCodeInformation) redisTemplate.opsForValue().get(state);
        if (redisToSaveCodeInformationToCheckExist != null) {
            redisTemplate.opsForValue().set(state, redisToSaveCodeInformation,360, TimeUnit.SECONDS);

        }else {
            return "登录验证码已经失效,请刷新二维码再扫码登录";
        }
        String openid = weChatUser.getOpenid();
        //TODO 这里检查是否用户已经绑定openid 是就直接返回成功信息,否则帮用户注册一个信息
        User userByOpenID = userService.findUserByOpenID(openid);
        if (userByOpenID == null) {
            //TODO 帮用户注册一个openID
            log.info("用户没有进行openID绑定");
            User user = new User();
            user.setUsername(weChatUser.getNickname());
            UUID uuid = UUID.randomUUID();
            String uuidStr = uuid.toString();
            user.setPassword(uuidStr);
            user.setOpenid(openid);
            userService.register(user);
            log.info("成功返回：{}", JSON.toJSONString(weChatUser));
            return "登录成功，请返回网页";
        }else {
            log.info("成功返回：{}", JSON.toJSONString(weChatUser));
            return "登录成功,请返回网页";
        }
    }


    @GetMapping("/wxUserGet")
    public Result weUserGet(HttpServletRequest request, HttpServletResponse response){
        String token = request.getHeader("token");
        redisToSaveCodeInformation redisToSaveCodeInformation = (redisToSaveCodeInformation) redisTemplate.opsForValue().get(token);
        if (redisToSaveCodeInformation != null && redisToSaveCodeInformation.getState() ==1) {
            WeChatUser information = (WeChatUser) redisToSaveCodeInformation.getInformation();
            String openid = information.getOpenid();
            Map<String,Object> map = new HashMap<>();
            map.put("openid", openid);
            String jwt = jwtUtils.getJwt(map);
            log.info("转化的token:{}", jwt);
            response.setHeader("token", jwt);

            return new  Result("登录成功", 200, redisToSaveCodeInformation.getInformation());
        }else {
            return new Result("验证未通过",400,null);
        }
    }
}